package com.bingo.util;

import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

/**
 * 日期操作工具类 
 * 使用java.time包相关类
 */
public class DateTools {
	public enum Pattern {
		SECOND_CENTER_LINE("yyyy-MM-dd HH:mm:ss"),
		DAY_CENTER_LINE("yyyy-MM-dd"),
		SECOND_NONE("yyyyMMddHHmmss"),
		DAY_NONE("yyyyMMdd"),
		SECONDE_DOT("yyyy.MM.dd HH:mm:ss"),
		DAY_DOT("yyyy.MM.dd");
		
		private String strPattern;
		private Pattern(String strPattern) {
			this.strPattern = strPattern;
		}
		public String getStrPattern() {
			return strPattern;
		}
	}
	/**
	 * LocalDateTime转java.util.Date
	 * @param ldt
	 * @return
	 */
	public static Date localDateTimeToDate(LocalDateTime ldt) {
		if(ldt == null) {
			return null;
		}
		ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zdt = ldt.atZone(zoneId);
        Date date = Date.from(zdt.toInstant());
        return date;
	}
	
	/**
	 * java.util.Date转LocalDateTime
	 * @param date
	 * @return
	 */
	public static LocalDateTime dateToLocalDateTime(Date date) {
		if(date == null) {
			return null;
		}
		 Instant instant = date.toInstant();
		 ZoneId zoneId = ZoneId.systemDefault();
		 LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
		 return localDateTime;
	}
	
	public static Date getDateNow() {
		return localDateTimeToDate(LocalDateTime.now());
	}
	
	public static Date getDate(int year) {
		return localDateTimeToDate(getLocalDateTime(year));
	}
	public static Date getDate(int year, int month) {
		return localDateTimeToDate(getLocalDateTime(year, month));
	}
	public static Date getDate(int year, int month, int dayOfMonth) {
		return localDateTimeToDate(getLocalDateTime(year, month, dayOfMonth));
	}
	public static Date getDate(int year, int month, int dayOfMonth, int hour) {
		return localDateTimeToDate(getLocalDateTime(year, month, dayOfMonth, hour));
	}
	public static Date getDate(int year, int month, int dayOfMonth, int hour, int minute) {
		return localDateTimeToDate(getLocalDateTime(year, month, dayOfMonth, hour, minute));
	}
	public static Date getDate(int year, int month, int dayOfMonth, int hour, int minute, int second) {
		return localDateTimeToDate(getLocalDateTime(year, month, dayOfMonth, hour, minute, second));
	}
	
	public static LocalDateTime getLocalDateTime(int year) {
		return getLocalDateTime(year, 1, 1, 0, 0);
	}
	public static LocalDateTime getLocalDateTime(int year, int month) {
		return getLocalDateTime(year, month, 1, 0, 0);
	}
	public static LocalDateTime getLocalDateTime(int year, int month, int dayOfMonth) {
		return getLocalDateTime(year, month, dayOfMonth, 0, 0);
	}
	public static LocalDateTime getLocalDateTime(int year, int month, int dayOfMonth, int hour) {
		return getLocalDateTime(year, month, dayOfMonth, hour, 0);
	}
	public static LocalDateTime getLocalDateTime(int year, int month, int dayOfMonth, int hour, int minute) {
		return LocalDateTime.of(year, month, dayOfMonth, hour, minute);
	}
	public static LocalDateTime getLocalDateTime(int year, int month, int dayOfMonth, int hour, int minute, int second) {
		return LocalDateTime.of(year, month, dayOfMonth, hour, minute, second);
	}
	
	public static int getYear(Date date) {
		return dateToLocalDateTime(date).getYear();
	}
	
	/**
	 * 获取月份数值从1开始
	 * @param date
	 * @return 1~12
	 */
	public static int getMonth(Date date) {
		return dateToLocalDateTime(date).getMonthValue();
	}
	
	/**
	 * @param date
	 * @return the day-of-month, from 1 to 31
	 */
	public static int getDayOfMonth(Date date) {
		return dateToLocalDateTime(date).getDayOfMonth();
	}
	
	/**
	 * @param date
	 * @return the day-of-year, from 1 to 365, or 366 in a leap year
	 */
	public static int getDayOfYear(Date date) {
		return dateToLocalDateTime(date).getDayOfYear();
	}
	
	/**
	 * @param date
	 * @return the day-of-week, from 1 (Monday) to 7 (Sunday)
	 */
	public static int getDayOfWeek(Date date) {
		return dateToLocalDateTime(date).getDayOfWeek().getValue();
	}
	
	/**
	 * @param date
	 * @return the hour-of-day, from 0 to 23
	 */
	public static int getHourOfDay(Date date) {
		return dateToLocalDateTime(date).getHour();
	}
	
	/**
	 * @param date
	 * @return the minute-of-hour, from 0 to 59
	 */
	public static int getMinuteOfHour(Date date) {
		return dateToLocalDateTime(date).getMinute();
	}
	
	/**
	 * @param date
	 * @return the second-of-minute, from 0 to 59
	 */
	public static int getSecondsOfMinute(Date date) {
		return dateToLocalDateTime(date).getSecond();
	}
	
	/**
	 * the number of milliseconds since January 1, 1970, 00:00:00 GMT represented by this date.
	 * @param date
	 * @return
	 */
	public static long getMilliSeconds(Date date) {
		return date.getTime();
	}
	
	/**
	 * 将时间对象偏移offset分钟，offset>0时间+offset分钟，offset<0时间-offset分钟
	 * @param date
	 * @param offset
	 * @return
	 */
	public static Date offMinute(Date date, int offset) {
		if(offset == 0) {
			return date;
		}
		return localDateTimeToDate(dateToLocalDateTime(date).plusMinutes(offset));
	}
	/**
	 * 将时间对象偏移offset小时，offset>0时间+offset小时，offset<0时间-offset小时
	 * @param date
	 * @param offset
	 * @return
	 */
	public static Date offHour(Date date, int offset) {
		if(offset == 0) {
			return date;
		}
		return localDateTimeToDate(dateToLocalDateTime(date).plusHours(offset));
	}
	/**
	 * 将时间对象偏移offset天，offset>0时间+offset天，offset<0时间-offset天
	 * @param date
	 * @param offset
	 * @return
	 */
	public static Date offDay(Date date, int offset) {
		if(offset == 0) {
			return date;
		}
		return localDateTimeToDate(dateToLocalDateTime(date).plusDays(offset));
	}
	/**
	 * 将时间对象偏移offset月，offset>0时间+offset月，offset<0时间-offset月
	 * @param date
	 * @param offset
	 * @return
	 */
	public static Date offMonth(Date date, int offset) {
		if(offset == 0) {
			return date;
		}
		return localDateTimeToDate(dateToLocalDateTime(date).plusMonths(offset));
	}
	/**
	 * 将时间对象偏移offset年，offset>0时间+offset年，offset<0时间-offset年
	 * @param date
	 * @param offset
	 * @return
	 */
	public static Date offYear(Date date, int offset) {
		if(offset == 0) {
			return date;
		}
		return localDateTimeToDate(dateToLocalDateTime(date).plusYears(offset));
	}
	/**
	 * 得到日期所在年的第一天开始时间
	 * @param date
	 * @return
	 */
	public static Date firstDayOfYear(Date date) {
		LocalDateTime ldt = dateToLocalDateTime(date);
		return localDateTimeToDate(getLocalDateTime(ldt.getYear()));
	}
	/**
	 * 得到日期对象所在月的第一天开始时间
	 * @param date
	 * @return
	 */
	public static Date firstDayOfMonth(Date date) {
		LocalDateTime ldt = dateToLocalDateTime(date);
		return localDateTimeToDate(getLocalDateTime(ldt.getYear(), ldt.getMonthValue()));
	}
	/**
	 * 得到日期对象所在日的开始时间
	 * @param date
	 * @return
	 */
	public static Date firstHourOfDay(Date date) {
		LocalDateTime ldt = dateToLocalDateTime(date);
		return localDateTimeToDate(getLocalDateTime(ldt.getYear(), ldt.getMonthValue(), ldt.getDayOfMonth()));
	}
	/**
	 * 得到日期所在周的第一天(星期一)开始时间
	 * @param date
	 * @return
	 */
	public static Date firstDayOfWeek(Date date) {
		int weekIndex = getDayOfWeek(date);
		int offset = weekIndex == 7 ? -6 :  1-weekIndex;
		return offDay(firstHourOfDay(date), offset);
	}
	/**
	 * 判断日期所在年是否为闰年
	 * @param date
	 * @return
	 */
	public static boolean isRunNian(Date date) {
		int year = getYear(date);
		if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0) {
			return true;
		} else {
			return false;
		}
	}
	/**
	 * 获取日期所在年共有多少天
	 * @param date
	 * @return
	 */
	public static int getTotalDaysOfYear(Date date) {
		return isRunNian(date) ? 366 : 365;
	}
	/**
	 * 获取日期所在月的总日数
	 * @param date
	 * @return
	 */
	public static int getTotalDaysOfMonth(Date date) {
		LocalDateTime ldt = dateToLocalDateTime(date);
		ldt = getLocalDateTime(ldt.getYear(), ldt.getMonthValue());
		ldt = ldt.plusMonths(1);
		ldt = ldt.minusDays(1);
		return ldt.getDayOfMonth();
	}
	/**
	 * 获取日期所在月的最后一天的开始时间
	 * @param date
	 * @return
	 */
	public static Date getLastDayOfMonth(Date date) {
		LocalDateTime ldt = dateToLocalDateTime(date);
		ldt = getLocalDateTime(ldt.getYear(), ldt.getMonthValue());
		ldt = ldt.plusMonths(1);
		ldt = ldt.minusDays(1);
		return localDateTimeToDate(ldt);
	}
	/**
	 * 字符串转日期
	 * @param dateStr 字符串各式日期，示例：2020-01-01 00:00:00
	 * @param pattern 日期格式枚举
	 * @return
	 */
	public static Date strToDate(String dateStr, Pattern pattern) {
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern.getStrPattern());
		return localDateTimeToDate(LocalDateTime.parse(dateStr, dtf));
	}
	
	/**
	 * 字符串转日期
	 * @param dateStr 字符串各式日期，示例：2020-01-01 00:00:00
	 * @param pattern 日期格式模板，示例：yyyy-MM-dd HH:mm:ss
	 * @return
	 */
	public static Date strToDate(String dateStr, String pattern) {
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
		return localDateTimeToDate(LocalDateTime.parse(dateStr, dtf));
	}
	/**
	 * 日期转字符串
	 * @param date
	 * @param pattern 日期格式枚举
	 * @return
	 */
	public static String dateToStr(Date date, Pattern pattern) {
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern.getStrPattern());
		LocalDateTime ldt = LocalDateTime.now();
		return ldt.format(dtf);
	}
	/**
	 * 日期转字符串
	 * @param date
	 * @param pattern 日期格式模板，示例：yyyy-MM-dd HH:mm:ss
	 * @return
	 */
	public static String dateToStr(Date date, String pattern) {
		DateTimeFormatter dtf = DateTimeFormatter.ofPattern(pattern);
		LocalDateTime ldt = LocalDateTime.now();
		return ldt.format(dtf);
	}

	public static void main(String[] args) {
		System.out.println(dateToStr(new Date(), Pattern.DAY_CENTER_LINE));
	}
}